#pragma once

#include"sock.hpp"
#include<sys/epoll.h>
#include<arpa/inet.h>
#include<unordered_map>
#define MAX_NUM 64

namespace ns_epoll
{
  class Epoller;
  class EventItem;

  typedef int(*callback_t)(EventItem*);  //const& 输入 * 输出 ， &输入输出

  const  int back_log = 5;
  const int size = 256;

  class EventItem{
    public:
      int sock;
      //回指Epoll
      Epoller* R;

      //有关数据处理的回调函数，应用数据就绪和数据处理模块使用方法进行解耦！
      
      callback_t recv_handler;
      callback_t send_handler;
      callback_t error_handler;

      std::string inbuffer;  //输入缓冲区
      std::string outbuffer; //输出缓冲区
    public:
      EventItem():sock(0),R(nullptr),recv_handler(nullptr),send_handler(nullptr),error_handler(nullptr)
    {}
      
      void ManagerCallBack(callback_t _recv,callback_t _send,callback_t _err)
      {
        recv_handler = _recv;
        send_handler = _send;
        error_handler = _err;
      }

      ~EventItem()
    {}
  };



  class Epoller{
    private:
      int listen_sock;
      int epfd;
      uint16_t port;

      std::unordered_map<int,EventItem> event_items;
      //sock:EventItem


    public:
      Epoller():epfd(-1)
      {}
      ~Epoller()
      {
        if(listen_sock >=0 ) close(listen_sock);
        if(epfd >= 0) close(epfd);
      }
    public:
      void initEpoller()
      {
        if((epfd = epoll_create(size))<0){
          std::cerr <<"epoll_create error!\n" <<std::endl;
          exit(4);
        }
        std::cout <<"debug. epfd: " <<epfd << std::endl;
      
      }
      void addEven(int sock,uint32_t event,const EventItem& item)
      {
        struct epoll_event ev;
        ev.events =  0;
        ev.events |= event;  //非必须
        ev.data.fd = sock;
        if(epoll_ctl(epfd,EPOLL_CTL_ADD,sock,&ev)<0){
          std::cerr << "epoll_ctrl error, fd:" << sock<<std::endl;
        }
        else{
          event_items.insert({sock,item});
        }
          
      }
      void delEvent(int sock)
      {
        if(epoll_ctl(epfd,EPOLL_CTL_DEL,sock,nullptr) <0){
          std::cerr << "epoll_ctl error, fd " << sock << std::endl;
        }
        event_items.erase(sock);
          
      }
      void EnableReadWrite(int sock,bool read,bool write)
      {
        struct epoll_event evt;
        evt.data.fd = sock;
        evt.events = (read?EPOLLIN : 0)| (write?EPOLLOUT:0)| EPOLLET;
        if(epoll_ctl(epfd,EPOLL_CTL_MOD,sock,&evt)<0){
          std::cerr << "epoll_ctl mod error. fd: " <<sock<< std::endl;
        }
      }

      //事件分派器
      void loopOnce(int timeout)
      {

        //如果底层特定的时间就绪，就把对应的事件分派给特定的回调函数进行处理

        //在这里我们目前只有一个socket是能够关心读写的,listen_sock,read event
        
        struct epoll_event revs[MAX_NUM];
        for(;;){
          //返回值num表明有多少个事件就绪了，内核会将就绪事件依次放入revs中
          int nums = epoll_wait(epfd,revs,MAX_NUM,timeout);
          if(nums > 0){
              for(int i = 0;i < nums;i++)
              {
                  int sock  = revs[i].data.fd;
                  if(revs[i].events & EPOLLIN)
                  {
                    //读时间就绪，调用读方法
                    if(event_items[sock].recv_handler){
                        event_items[sock].recv_handler(&event_items[sock]);
                    }
                    if(revs[i].events & EPOLLOUT){
                      if(event_items[sock].send_handler){
                        event_items[sock].send_handler(&event_items[sock]);
                      }
                    }
                    if(revs[i].events & EPOLLERR){
                      if(event_items[sock].error_handler){
                        event_items[sock].error_handler(&event_items[sock]);
                      }

                    }

                  }
              }
          }
          else{

            std::cout << "epoll error" << std::endl;
          }

        }



    
      }

  };
}
